use std::collections::HashMap;

use crate::data::VCData;
use bytestring::ByteString;
use serde::{Deserialize, Serialize};


#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct WsRequest {
    // 事件
    pub evt: WsEvent,
    // json数据
    pub vcd: VCData,

}

impl WsRequest {

    pub fn from_str<'a>(s: &'a str) -> Result<Self, serde_json::Error> {
        serde_json::from_str(s)
    }

    #[allow(dead_code)]
    pub fn to_str(&self) -> Result<String, serde_json::Error> {
        serde_json::to_string(self)
    }

    pub fn to_bytestr(&self) -> ByteString {
        let buf: ByteString = serde_json::to_string(self).unwrap().to_owned().into();
        buf
    }
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct WsResponse {
    // 事件
    pub evt: Option<WsEvent>,
    // 结果
    pub res: WsResult,
    // 消息
    pub msg: String,
    // json数据
    pub vcd: Option<VCData>,
    // 实际数据
    pub dat: Option<HashMap<String, HashMap<String, String>>>
}

// #[derive(Debug, Clone, Deserialize, Serialize)]
// pub struct Payload {
//     // 服务名：命名空间
//     pub sn: HashMap<String, String>,
//     // 路径
//     pub p: String, 
//     // 操作：删除，替换，新增
//     pub k: PayloadKind,
//     // 文件名
//     // pub file_name: String,
//     // 数据
//     pub d: Option<Vec<u8>>,
//     // Data End
//     pub de: bool,
// }

#[derive(Debug, Clone, Deserialize, Serialize)]
pub enum PayloadKind {
    C,
    Cd,
    R,
    Rd,
    X,
    D,
    Ma,
    Mp,
    Mm,
}

impl PayloadKind {
    
    // pub(crate) fn is_modify(self) -> bool {
    //     match self {
    //         PayloadKind::Modify => true,
    //         _ => false
    //     }
    // } 

    // pub(crate) fn is_remove(self) -> bool {
    //     match self {
    //         PayloadKind::Remove => true,
    //         _ => false
    //     }
    // } 
}

#[derive(Debug, Clone, Deserialize, Serialize)]
pub enum WsResult {
    // 处理成功
    Ok,
    // 指的是处理失败
    Failed,
    // 指的是处理过程有发生异常
    Error,
}



#[derive(Debug, Clone, Deserialize, Serialize)]
pub enum WsEvent {
    // Ping Pong
    PP,
    // 同步数据: Data Sync.
    DS,
    // 投票: Leader Vote
    LV,
    // 广播数据：传递数据到其他节点
    TV,
    // Leader ACK,
    LA,
    // Follower ACK
    FA,
    // 无需投票
    // NV,
    // 重置数据
    // RS,
    // // 降级为Follower
    // Follower,
    // // leader下线
    // LeaderOffline,
    // 普通节点下线
    // Offline,
    // 节点内部通讯: Heartbeat
    // HB,
    // // Heartbeat Leader
    // HL, 
    // // Heartbeat Follower
    // HF,

    // 清理投票信息：Reset Voting
    RV,
    // 广播文件
    BF,
}




// #[derive(Debug, Clone, Deserialize, Serialize)]
// pub struct Attribute {
//     pub id: usize,
//     // 任期数
//     pub term: usize,
//     // 投票数
//     pub poll: usize,
//     // 事务次数，每同步一次数据后 +1
//     pub tranx: usize,
//     // 数据同步情况
//     pub status: WsDataStatus

// }

// 0 => 本机刚恢复,投票周期比加入的节点要小,本机需要同步数据
// 1 => 本机投票周期比加入节点的要大,加入节点需要同步数据
// 2 => 投票周期一致
#[derive(Debug, Clone, Deserialize, Serialize)]
pub enum WsDataStatus {
    // 本机需同步数据
    RECV,
    // 其他节点需要同步数据
    SEND,
    // 投票周期一致
    NONTODO,
}

impl WsResponse {
    pub fn from_str<'a>(s: &'a str) -> Result<Self, serde_json::Error> {
        serde_json::from_str(s)
    }

    pub fn ok(evt: Option<WsEvent>, msg: String, vcd: Option<VCData>) -> Self {
        WsResponse {
            evt,
            res: WsResult::Ok,
            msg,
            vcd,
            dat: None
        }
    }

    pub fn failed(evt: Option<WsEvent>, msg: String, vcd: Option<VCData>) -> Self {
        WsResponse {
            evt,
            res: WsResult::Failed,
            msg,
            vcd,
            dat: None
        }
    }

    pub fn error(evt: Option<WsEvent>, msg: String, vcd: Option<VCData>) -> Self {
        WsResponse {
            evt,
            res: WsResult::Error,
            msg,
            vcd,
            dat: None
        }
    }

    pub fn to_string(&self) -> String {
        serde_json::to_string(&self).unwrap()
    }

    #[allow(dead_code)]
    pub fn to_bytestr(&self) -> ByteString {
        let buf: ByteString = serde_json::to_string(self).unwrap().to_owned().into();
        buf
    }

    // pub fn new() -> Self {
    //     WsResponse { event: WsEvent::UNKNOWN, status_code: WsStatusCode::SUCCESS, mail_box: String::new(), state: None }
    // }
}

// impl Attribute {
//     pub fn new(node: Node) -> Self {
//         Attribute { id: node.id, term: node.term, poll: node.poll, tranx: node.tranx, status: WsDataStatus::RECV }
//     }

// }
